#ifndef XLCOMM_NET_SOCKET_H_
#define XLCOMM_NET_SOCKET_H_

#include "xlcomm/net/inet_address.h"
#include "xlcomm/noncopyable.h"

namespace xlcomm {
namespace net {

// RAII封装套接字。析构时自动close sockfd，不要在外部close
class Socket : noncopyable {
 public:
  explicit Socket(int sockfd);
  ~Socket();

  // 绑定IP地址和端口号。失败直接退出程序
  void Bind(const InetAddress& local_addr);

  // 监听新连接。失败直接退出程序
  void Listen();

  // 接受新连接，填充对端地址，返回新连接的文件描述符
  int Accept(InetAddress* peer_addr);

  // 停止写入
  bool ShutdownWrite();

  // 设置 SO_REUSEADDR 选项（避免处于TIME_WAIT状态时bind失败，用于快速重启服务）
  bool SetReuseAddr(bool on);
  // 设置 SO_REUSEPORT 选项（允许多个进程/线程bind listen相同的IP:PORT）
  bool SetReusePort(bool on);
  // 设置 TCP_NODELAY 选项
  bool SetTcpNoDelay(bool on);
  // 设置 SO_KEEPALIVE 选项
  bool SetKeepAlive(bool on);

  int sockfd() const { return sockfd_; }

 private:
  const int sockfd_;
};

}  // namespace net
}  // namespace xlcomm

#endif  // XLCOMM_NET_SOCKET_H_